package org.hackystat.ui.telemetryviewer.gwt.server;

import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

import org.hackystat.ui.telemetryviewer.gwt.client.ChartGeneratorRPC;
import org.restlet.Client;
import org.restlet.data.Method;
import org.restlet.data.Protocol;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.resource.Representation;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * Implements server side of the ChartGenerator service.
 *
 * @author Pavel Senin.
 *
 */
public class ChartGeneratorRPCImpl
    extends RemoteServiceServlet implements ChartGeneratorRPC {

  static final String dependencyToken = "dependency";

  static final String junitToken = "junit";

  static final char dependencyDelimiter = '#';

  private static final long serialVersionUID = -8261231970407498849L;

  /**
   * Generates chart according to parameters given.
   *
   * @param type specifies the chart type.
   * @return the path to the chart generated.
   */
  public String generateChart(String type) {
    /*
     * Hold our stored chart name, it will be returned to the GWT caller.
     */
    String chartName = "";

    if (type.startsWith(junitToken)) {
      try {
        // Generate the junit chart.

        // but break the coding string first
        String[] breakedToken = type.substring(
            type.indexOf(ChartGeneratorRPCImpl.dependencyDelimiter) + 1, type.length())
            .split("\\#");

        // get the couple of datasets first
        String spanToken = breakedToken[0];

        // set the dates
        Calendar calendar = new GregorianCalendar();
        calendar.setTimeInMillis(System.currentTimeMillis());
        Date endDate = calendar.getTime();
        Date startDate = calendar.getTime();

        if ("7d".equals(spanToken)) {
          calendar.add(Calendar.WEEK_OF_YEAR, -1);
          startDate = calendar.getTime();
        }
        else if ("14d".equals(spanToken)) {
          calendar.add(Calendar.WEEK_OF_YEAR, -2);
          startDate = calendar.getTime();
        }
        else if ("1m".equals(spanToken)) {
          calendar.add(Calendar.MONTH, -1);
          startDate = calendar.getTime();
        }
        else if ("3m".equals(spanToken)) {
          calendar.add(Calendar.MONTH, -3);
          startDate = calendar.getTime();
        }
        else if ("6m".equals(spanToken)) {
          calendar.add(Calendar.MONTH, -6);
          startDate = calendar.getTime();
        }
        else if ("1y".equals(spanToken)) {
          calendar.add(Calendar.YEAR, -1);
          startDate = calendar.getTime();
        }

        StringBuffer URLString = new StringBuffer(500);

        URLString.append("http://localhost:3128/jfcs/chart/junit?startTime=");

        DatatypeFactory factory = DatatypeFactory.newInstance();

        calendar.setTime(startDate);
        XMLGregorianCalendar cal1 = factory.newXMLGregorianCalendarDate(
            calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar
                .get(Calendar.DAY_OF_MONTH), DatatypeConstants.FIELD_UNDEFINED);

        URLString.append(cal1.toString());

        calendar.setTime(endDate);

        cal1 = factory.newXMLGregorianCalendarDate(calendar.get(Calendar.YEAR), calendar
            .get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH),
            DatatypeConstants.FIELD_UNDEFINED);
        URLString.append("&endTime=");

        URLString.append(cal1.toString());

        // Prepare the request
        Request request = new Request(Method.GET, URLString.toString());
        request.setReferrerRef("http://www.mysite.org");

        // Handle it using an HTTP client connector
        Client client = new Client(Protocol.HTTP);
        Response response = client.handle(request);

        // Write the response entity on the console
        Representation output = response.getEntity();

        chartName = "http://localhost:3128/jfcs/file/" + output.getText();

      }
      catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      catch (DatatypeConfigurationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }

    }
    else if (type.startsWith(dependencyToken)) {
      try {
        // Generate the dependency chart.
        // but break the coding string first
        String[] breakedToken = type.substring(
            type.indexOf(ChartGeneratorRPCImpl.dependencyDelimiter) + 1, type.length())
            .split("\\#");

        // get the couple of datasets first
        String dateToken = breakedToken[0];

        // set the dates
        Calendar calendar = new GregorianCalendar();
        calendar.setTimeInMillis(System.currentTimeMillis());
        Date endDate = calendar.getTime();
        Date startDate = calendar.getTime();

        if ("7d".equals(dateToken)) {
          calendar.add(Calendar.WEEK_OF_YEAR, -1);
          startDate = calendar.getTime();
        }
        else if ("14d".equals(dateToken)) {
          calendar.add(Calendar.WEEK_OF_YEAR, -2);
          startDate = calendar.getTime();
        }
        else if ("1m".equals(dateToken)) {
          calendar.add(Calendar.MONTH, -1);
          startDate = calendar.getTime();
        }
        else if ("3m".equals(dateToken)) {
          calendar.add(Calendar.MONTH, -3);
          startDate = calendar.getTime();
        }
        else if ("6m".equals(dateToken)) {
          calendar.add(Calendar.MONTH, -6);
          startDate = calendar.getTime();
        }
        else if ("1y".equals(dateToken)) {
          calendar.add(Calendar.YEAR, -1);
          startDate = calendar.getTime();
        }

        StringBuffer URLString = new StringBuffer(500);

        URLString.append("http://localhost:3128/jfcs/chart/dependency?startTime=");

        DatatypeFactory factory = DatatypeFactory.newInstance();

        calendar.setTime(startDate);
        XMLGregorianCalendar cal1 = factory.newXMLGregorianCalendarDate(
            calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar
                .get(Calendar.DAY_OF_MONTH), DatatypeConstants.FIELD_UNDEFINED);

        URLString.append(cal1.toString());

        calendar.setTime(endDate);

        cal1 = factory.newXMLGregorianCalendarDate(calendar.get(Calendar.YEAR), calendar
            .get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH),
            DatatypeConstants.FIELD_UNDEFINED);
        URLString.append("&endTime=");

        URLString.append(cal1.toString());

        // adding the series information
        // URLString.append("&afferentCouplings=" + breakedToken[1]);
        // URLString.append("&efferentCouplings=" + breakedToken[2]);
        // URLString.append("&cycles=" + breakedToken[3]);

        // Prepare the request
        Request request = new Request(Method.GET, URLString.toString());
        request.setReferrerRef("http://www.mysite.org");

        // Handle it using an HTTP client connector
        Client client = new Client(Protocol.HTTP);
        Response response = client.handle(request);

        // Write the response entity on the console
        Representation output = response.getEntity();

        chartName = "http://localhost:3128/jfcs/file/" + output.getText();

      }
      catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      catch (DatatypeConfigurationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }

    }

    /*
     * Finally, return the chart name to the caller.
     */
    return chartName;
  }

  // /**
  // * Calculates the date from a span given.
  // *
  // * @param periodEnd the end of Time period.
  // * @param span the span value.
  // * @return the date which is the real start of period.
  // */
  // private Date getDateFromSpan(Date periodEnd, int span) {
  // Calendar calendar = new GregorianCalendar();
  // calendar.setTime(periodEnd);
  // calendar.add(Calendar.DAY_OF_YEAR, -span);
  // return calendar.getTime();
  //  }

}